home *** CD-ROM | disk | FTP | other *** search
- /* MeterMain.c - test rig for designing meters, illustrating the interaction
- between documents, windows, and controls
- by Ken Earle, 1989
- ThinkC 3.0 settings:
- Options...; <MacHeaders>, Check Pointers, Require Protoypes
- Set Project Type...; File Type APPL, Creator whatever
- Files: MacTraps
- Math
- Meter.c MeterMain.c
- Headers: <MacHeaders> <math.h> "Meter.h"
- Resources: none (What? Blasphemy!)
- */
-
- #include "Meter.h"
- #define APPLEID 15
- #define FILEID 16
- #define EDITID 17
- #define QUIT 12
- #define HSCROLL 1L /* scroll bar ID */
- #define VSCROLL 2L
- #define SCROLLSIZE 15
- #define DOCHEIGHT 720 /* 10" x 72 */
- #define DOCWIDTH 576 /*8" x 72 */
- #define MAXWINDOWWIDTH (DOCWIDTH + SCROLLSIZE)
- #define MAXWINDOWHEIGHT (DOCHEIGHT + SCROLLSIZE)
- #define DISPLAYBOXWIDTH 72 /* <= 0 removes the display
- and disables DrawDisplayBox() */
-
- /* display modes are used by DrawDisplayBox() */
- enum DisplayMode
- {
- forWindow, forMeter, forThumb, forDebug = 300 /* forces to 16-bit size */
- };
- typedef enum DisplayMode DisplayMode;
-
- /* useful globals */
- WindowRecord wRecord1, wRecord2;
- RgnHandle updateRgn;
- MenuHandle appleMenu, fileMenu, editMenu;
- /* handy globals */
- Rect dragRect = { 0, 0, 1024, 1024 };
- char wTitle1[] = "\PRear Window";
- char wTitle2[] = "\PFront Window";
- char mTitle1[] = "\PFirst Meter";
- char mTitle2[] = "\PSecond Meter";
- char mTitle3[] = "\PThird Meter";
- char mTitle4[] = "\PFourth Meter";
-
- /* Prototypes for functions defined in this file */
- int main(void);
- void DoStandardInits(void);
- void MakeMenus(void);
- Boolean DoMenu(long);
- void MakeTwoWindows(void);
- void MakeTwoMeters(WindowPtr, int);
- void DitherMeters(void);
- void DoContent(WindowPtr, EventRecord*);
- void UpdateContents(WindowPtr, Boolean);
- void DrawDisplayBox(WindowPtr, void**, DisplayMode, int, int);
- void DoZoomWindow (WindowPtr, int);
- void DoGrowWindow(EventRecord*);
- void DoCloseWindow(void);
- Boolean AMeterWindow(WindowPtr);
- void GetScrollHandles(WindowPtr, ControlHandle*, ControlHandle*);
- void LocalToDoc(Point*);
- void MeterProc(MeterHandle, int);
- pascal void ScrollProc(ControlHandle,int);
- void ThumbControl(ControlHandle, Point);
- void PutMetersOnClip(WindowPtr);
-
- main()
- {
- int part;
- EventRecord myEvent;
- WindowPtr whichWindow;
- GrafPtr savePort;
- MeterHandle mH;
- ControlHandle cH;
- Rect cRect; /* see "activateEvt" */
- RgnHandle tempRgn; /* see updateEvt */
- Boolean quitting = FALSE;
-
- DoStandardInits();
- updateRgn = NewRgn();
- MakeMenus();
- MakeTwoWindows();
-
- do /* while not quitting */
- {
- do /* while no next event */
- {
- SystemTask();
- DitherMeters();
- } while (!GetNextEvent(everyEvent, &myEvent));
- switch (myEvent.what)
- {
- case mouseDown:
- switch (part = FindWindow( myEvent.where, &whichWindow ))
- {
- case inDesk:
- SysBeep(2);
- break;
- case inMenuBar:
- quitting = DoMenu(MenuSelect(myEvent.where));
- case inSysWindow:
- SystemClick( &myEvent, whichWindow );
- break;
- case inDrag:
- if (AMeterWindow(whichWindow))
- DragWindow( whichWindow, myEvent.where, &dragRect );
- break;
- case inZoomIn:
- case inZoomOut:
- if (AMeterWindow(whichWindow))
- if (TrackBox(whichWindow, myEvent.where, part))
- DoZoomWindow (whichWindow, part);
- break;
- case inGrow:
- if (AMeterWindow(whichWindow))
- DoGrowWindow(&myEvent);
- break;
- case inGoAway:
- if (AMeterWindow(whichWindow))
- if (TrackGoAway (whichWindow, myEvent.where))
- DoCloseWindow();
- break;
-
- case inContent:
- if (whichWindow != FrontWindow())
- SelectWindow(whichWindow);
- else
- if (AMeterWindow(whichWindow))
- DoContent(whichWindow, &myEvent);
- break;
- default:
- break;
- } /* switch FindWindow */
- break;
- case keyDown:
- case autoKey:
- break;
- case activateEvt:
- whichWindow = (WindowPtr)myEvent.message;
- if (AMeterWindow(whichWindow))
- {
- mH = (MeterHandle)(((WindowPeek)whichWindow)->refCon);
- cH = ((WindowPeek)whichWindow)->controlList;
- if ( myEvent.modifiers & activeFlag )
- {
- SetPort(whichWindow);
- ClipRect(&(whichWindow->portRect));
- InvalRect(&(whichWindow->portRect));
- DrawGrowIcon(whichWindow);
- if (cH)
- {
- while (cH)
- {
- ShowControl(cH);
- cRect = (**cH).contrlRect;
- ValidRect(&cRect);
- cH = (**cH).nextControl;
- }
- }
- if (ValidMeter(mH))
- {
- while (mH)
- {
- /* activate meters */
- (**mH).meterHilite = 0;
- mH = (**mH).nextMeter;
- }
- }
- cRect = thePort->portRect;
- cRect.bottom -= SCROLLSIZE;
- cRect.right -= SCROLLSIZE;
- ClipRect(&cRect);
- } /* if activate */
- else
- {
- GetPort(&savePort);
- SetPort(whichWindow);
- ClipRect(&(whichWindow->portRect));
- InvalRect(&(whichWindow->portRect));
- DrawGrowIcon(whichWindow);
- if (cH)
- {
- while(cH)
- {
- HideControl(cH);
- cH = (**cH).nextControl;
- }
- }
- if (ValidMeter(mH))
- {
- while (mH)
- {
- /* deactivate meters */
- (**mH).meterHilite = 255;
- mH = (**mH).nextMeter;
- }
- }
- SetPort(savePort);
- } /* else deactivate */
- } /* if our window */
- break;
- case updateEvt:
- whichWindow = (WindowPtr)myEvent.message;
- if (AMeterWindow(whichWindow))
- {
- GetPort(&savePort);
- SetPort( whichWindow );
- ClipRect(&whichWindow->portRect);
- BeginUpdate( whichWindow );
- EraseRect(&whichWindow->portRect);
- DrawGrowIcon(whichWindow);
- DrawControls(whichWindow);
- DrawDisplayBox(whichWindow, 0L, forWindow,0,0);
- /* Take the scrolls out of updateRgn, because
- UpdateContents() sets the clip region to the
- (global) updateRgn. */
- CopyRgn(whichWindow->visRgn,updateRgn);
- tempRgn = NewRgn();
- SetRectRgn(tempRgn, whichWindow->portRect.left,
- whichWindow->portRect.bottom - SCROLLSIZE,
- whichWindow->portRect.right,
- whichWindow->portRect.bottom);
- DiffRgn(updateRgn, tempRgn, updateRgn);
- SetRectRgn(tempRgn, whichWindow->portRect.right - SCROLLSIZE,
- whichWindow->portRect.top,
- whichWindow->portRect.right,
- whichWindow->portRect.bottom - SCROLLSIZE);
- DiffRgn(updateRgn, tempRgn, updateRgn);
- DisposeRgn(tempRgn);
- /* Redraw the "true contents" of the window. */
- UpdateContents(whichWindow, (whichWindow == FrontWindow()));
- EndUpdate( whichWindow );
- SetPort(savePort);
- }
- break;
- default:
- break;
- } /* switch myEvent.what */
- } while (!quitting);
- if (FrontWindow())
- PutMetersOnClip(FrontWindow());
- } /* end main() */
-
- void DoStandardInits()
- {
-
- MoreMasters();
- MoreMasters();
- MoreMasters();
- InitGraf(&thePort);
- InitFonts();
- FlushEvents(everyEvent, 0);
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(0L);
- InitCursor();
- }/* end DoStandardInits() */
-
- void MakeMenus()
- {
-
- appleMenu = NewMenu(APPLEID,"\P\24");
- AppendMenu(appleMenu,"\P(About nothing...;(-");
- AddResMenu(appleMenu,'DRVR');
- InsertMenu(appleMenu,0);
-
- fileMenu = NewMenu(FILEID,"\PFile");
- AppendMenu(fileMenu,"\PNew;Open...;(-;Close;Save;Save as...;Revert;(-;Page Setup...;Print...;(-;Quit/Q");
- InsertMenu(fileMenu,0);
-
- editMenu = NewMenu(EDITID,"\PEdit");
- AppendMenu(editMenu,"\PUndo/Z;(-;Cut/X;Copy/C;Paste/V;Clear;(-;Show Clipboard;Select All");
- InsertMenu(editMenu,0);
-
- DrawMenuBar();
-
- } /* end MakeMenus() */
-
- /* DoMenu returns TRUE when quit selected */
- Boolean DoMenu(menuAndItem)
- long menuAndItem;
- {
- int theItem;
- char name[64];
-
- theItem = LoWord(menuAndItem);
- switch (HiWord(menuAndItem))
- {
- case APPLEID:
- if (theItem > 1)
- {
- if (FrontWindow())
- PutMetersOnClip(FrontWindow());
- GetItem(appleMenu, theItem, name);
- OpenDeskAcc(name);
- }
- break;
- case FILEID:
- if (theItem == QUIT)
- return(TRUE);
- break;
- case EDITID:
- break;
- default:
- break;
- }
- HiliteMenu(0);
- return(FALSE);
- } /* end DoMenu() */
-
- /* Make two windows right off the bat, each with a couple of scroll bars
- and a couple of meters. The windows are sized to fit the screen, but limited
- to a maximum size of 8" by 10" to show the slight complications that arise when
- dealing with a fixed document size. The trick thereafter is to ensure that you
- never stray outside the document - see DoGrowWindow() etc */
- void MakeTwoWindows()
- {
- int i, topGap, winWidth, winHeight;
- int horRange, vertRange;
- Rect boundsRect, cRect, clpRect;
- WindowPtr wPtr;
- ControlHandle cH;
- WStateData *wsd;
-
- /* Old small screen, or something bigger?
- topGap = menu bar height + 20 for the window frame */
- if ((screenBits.bounds.bottom - screenBits.bounds.top) < 343)
- topGap = MBarHeight + 20;
- else
- topGap = 60;
- /* topGap + window height + all offsets(1 here) + 4(at the bottom) = screen height */
- winHeight = ((screenBits.bounds.bottom - screenBits.bounds.top - topGap - 14) <= MAXWINDOWHEIGHT) ?
- (screenBits.bounds.bottom - screenBits.bounds.top - topGap - 14) : MAXWINDOWHEIGHT;
- winWidth = ((screenBits.bounds.right - screenBits.bounds.left - 18) <= MAXWINDOWWIDTH) ?
- (screenBits.bounds.right - screenBits.bounds.left - 18) : MAXWINDOWWIDTH;
- SetRect(&boundsRect, 4, topGap, 4 + winWidth, topGap + winHeight);
- /* Scroll bar ranges: range = amount of document left unseen (honest!) */
- vertRange = MAXWINDOWHEIGHT - (boundsRect.bottom - boundsRect.top);
- vertRange = (vertRange > 0) ? vertRange : 0;
- horRange = MAXWINDOWWIDTH - (boundsRect.right - boundsRect.left);
- horRange = (horRange > 0) ? horRange : 0;
- /* Create two windows, offset slightly */
- for (i = 1; i <= 2; ++i)
- {
- if (i == 1)
- wPtr = NewWindow(&wRecord1, &boundsRect, wTitle1, TRUE, 8,-1L,TRUE, 0L);
- else
- {
- OffsetRect(&boundsRect, 10, 10);
- wPtr = NewWindow(&wRecord2, &boundsRect, wTitle2, TRUE, 8,-1L,TRUE, 0L);
- }
- SetPort(wPtr);
- ClipRect(&(thePort->portRect));
- /* Adjust zoom rectangles since document size is fixed. */
- wsd = (WStateData*)*(((WindowPeek)wPtr)->dataHandle);
- wsd->stdState = boundsRect;
- wsd->userState = boundsRect;
- /* horizontal bar */
- /* Note room is reserved at right of the bar for the
- display box - see DrawDisplayBox(). */
- cRect.top = thePort->portRect.bottom - SCROLLSIZE;
- cRect.left = thePort->portRect.left - 1;
- cRect.bottom = thePort->portRect.bottom + 1;
- cRect.right = thePort->portRect.right - DISPLAYBOXWIDTH - 14;
- cH = NewControl(thePort,&cRect,"\P",TRUE,0,0,horRange,scrollBarProc,HSCROLL);
- if (horRange == 0)
- HiliteControl(cH, 255);
- /* vertical bar */
- cRect.top = thePort->portRect.top - 1;
- cRect.left = thePort->portRect.right - SCROLLSIZE;
- cRect.bottom = thePort->portRect.bottom - 14;
- cRect.right = thePort->portRect.right + 1;
- cH = NewControl(thePort,&cRect,"\P",TRUE,0,0,vertRange,scrollBarProc,VSCROLL);
- if (vertRange == 0)
- HiliteControl(cH, 255);
- clpRect = thePort->portRect;
- clpRect.bottom -= SCROLLSIZE;
- clpRect.right -= SCROLLSIZE;
- ClipRect(&clpRect);
- MakeTwoMeters(wPtr, i);
- }
- }/* end MakeTwoWindows() */
-
- /* Create four meters, two in each window. Note that it is not necessary to
- carry around all the meterhandles as globals since they are attached to the
- window's refCon field as a linked list by NewMeter(). */
- void MakeTwoMeters(wPtr, which)
- WindowPtr wPtr;
- int which;
- {
- Rect boundsRect;
- MeterHandle mH;
-
- if (which == 1)
- {
- boundsRect.top = 0;
- boundsRect.left = 0;
- boundsRect.bottom = 0;
- boundsRect.right = 144; /* 2 inches wide */
- mH = NewMeter(wPtr, &boundsRect, mTitle1, FALSE, 256L, 0L, 512L, 0L);
- (**mH).meterVis = TRUE;
- (**mH).meterHilite = 255;
- boundsRect.left = 150;
- boundsRect.right = 222; /* 1 inch wide */
- mH = NewMeter(wPtr, &boundsRect, mTitle2, FALSE, 0L, -1000L, 1000L, 0L);
- (**mH).meterVis = TRUE;
- (**mH).meterHilite = 255;
- }
- else if (which == 2) /* the front window at first */
- {
- boundsRect.top = 10;
- boundsRect.left = 50;
- boundsRect.bottom = 0;
- boundsRect.right = 158;
- NewMeter(wPtr, &boundsRect, mTitle3, TRUE, 2000L, 0L, 4095L, 0L);
- boundsRect.left = 204;
- boundsRect.right = 384;
- NewMeter(wPtr, &boundsRect, mTitle4, TRUE, 0L, -40950L, 40950L, 0L);
- }
- }/* end MakeTwoMeters() */
-
- /* Shake the needle around the setpoint to see it move. Affects
- all meters in the front window. */
- void DitherMeters()
- {
- static int random = 0;
- static long oldVal = 0L;
- long val, setVal, posIncrement, newVal;
- int direction, docV, docH;
- ControlHandle cHH, cHV;
- MeterHandle mH = (MeterHandle)(((WindowPeek)thePort)->refCon);
-
- if (ValidMeter(mH))
- {
- Delay(0L, &newVal);
- if (newVal - oldVal > 8L) /* time delay */
- {
- if (random > 0)
- direction = 1;
- else if (random < 0)
- direction = -1;
- else
- direction = 0;
- oldVal = newVal;
- /* get control handles */
- GetScrollHandles(thePort, &cHH, &cHV);
- /* find where we've scrolled to */
- docV = GetCtlValue(cHV);
- docH = GetCtlValue(cHH);
- /* shift to the right location in the document */
- SetOrigin(docH, docV);
- OffsetRgn(thePort->clipRgn, docH, docV);
- /* run through all the meters for this window */
- while (ValidMeter(mH))
- {
- val = (**mH).needleValue;
- setVal = (**mH).meterValue;
- posIncrement = ((**mH).meterMax - (**mH).meterMin)/250L;
- newVal = val + (setVal - val)/10L + direction*posIncrement;
- SetNeedleValue(mH, newVal);
- mH = (**mH).nextMeter;
- }
- SetOrigin(0, 0);
- OffsetRgn(thePort->clipRgn, -docH, -docV);
- ++random;
- if (random >= 5)
- random = -5;
- }
- }
- }/* end DitherMeters() */
-
- /* Handle Mouse down in our window - can hit scroll bars or meters. */
- void DoContent(theWindow, theEvent)
- WindowPtr theWindow;
- EventRecord *theEvent;
- {
- int cntlCode, axis;
- int docV, docH;
- int oldMWidth, newMWidth;
- Point startPoint, endPoint;
- ControlHandle theCtl, cHH, cHV;
- MeterHandle theMeter;
- Rect limitRect, slopRect;
-
- startPoint = theEvent->where;
- GlobalToLocal(&startPoint);
- /* First handle scroll bar events... */
- if ((cntlCode = FindControl(startPoint,theWindow,&theCtl)) != 0)
- {
- if (cntlCode >= inUpButton && cntlCode <= inPageDown) /* scroll, not thumb */
- TrackControl(theCtl,startPoint,&ScrollProc);
- else if (cntlCode == inThumb)
- {
- /* Ordinarily you would call TrackControl(theCtl,startPoint, 0L)
- but today we're doing "real-time" thumb control. */
- ThumbControl(theCtl, startPoint);
- } /* else if in thumb */
- } /* if in a control */
- /* ...then handle "true content" mouse events. */
- else
- {
- /* We're going to treat the meters as being attached to the
- underlying document rather than the window frame, so we must shift to
- "document" coordinates before determining which meter was hit. */
- LocalToDoc(&startPoint);
- if ((cntlCode = FindMeter(startPoint,theWindow,&theMeter)) != 0)
- {
- /* Shift everything to document coordinates before proceeding: */
- /* 1 - get control handles */
- GetScrollHandles(theWindow, &cHH, &cHV);
- /* 2 - find where we've scrolled to */
- docV = GetCtlValue(cHV);
- docH = GetCtlValue(cHH);
- /* 3 - shift to the right location in the document */
- SetOrigin(docH, docV);
- OffsetRgn(theWindow->clipRgn, docH, docV);
- /* 4 - now deal with events as though no scrolling has
- taken place */
- if (theEvent->modifiers & optionKey)
- {
- /* Drag the meter around. This is very handy since meters take
- up a lot of screen. Unneeded meters can be slid almost entirely
- off the screen to make room for other things. */
- slopRect = limitRect = thePort->portRect;
- InsetRect(&limitRect, 10, 10);
- limitRect.right -= SCROLLSIZE;
- limitRect.bottom -=SCROLLSIZE;
- axis = 0; /* no constraint */
- DragMeter(theMeter, startPoint, &limitRect, &slopRect, axis);
- }
- else if (theEvent->modifiers & cmdKey)
- {
- /* Resize the meter while mouse down - useful when playing
- with the look of the meter, and shows how the display box
- can be a very handy design tool. */
- oldMWidth = (**theMeter).meterRect.right - (**theMeter).meterRect.left;
- while (StillDown())
- {
- GetMouse(&endPoint); /* still in unscrolled coord's */
- newMWidth = oldMWidth - startPoint.h + endPoint.h;
- SizeMeter(theMeter, newMWidth);
- DrawDisplayBox(theWindow, (void**)theMeter, forMeter, 0,0);
- }
- }
- else if (cntlCode >= inUpButton && cntlCode <= inPageDown) /* not background */
- TrackMeter(theMeter,startPoint,&MeterProc);
- else if (cntlCode == inBackground)
- {
- /* default for inBackGround just shows set point value */
- TrackMeter(theMeter,startPoint,0L);
- }
- SetOrigin(0, 0);
- OffsetRgn(theWindow->clipRgn, -docH, -docV);
- } /* if FindMeter */
- } /* else true content */
- } /* end DoContent() */
-
- /* The all-purpose redraw function, draws only what touches
- the update region and handles scroll bars so that the routines
- which draw individual items don't have to keep track of where
- we've scrolled to in the document. Can even be used for printing,
- provided you temporarily set the scroll bar values to the minimum
- and the updateRgn to the whole document beforehand, and provided your
- individual drawing routines don't set the port before drawing. */
- void UpdateContents(wPtr, frontMost)
- WindowPtr wPtr;
- Boolean frontMost;
- {
- int docV, docH;
- Rect clpRect;
- ControlHandle cHH, cHV;
- MeterHandle mH = (MeterHandle)(((WindowPeek)wPtr)->refCon);
-
- SetClip(updateRgn);
- /* get control handles */
- GetScrollHandles(wPtr, &cHH, &cHV);
- /* find where we've scrolled to */
- docV = GetCtlValue(cHV);
- docH = GetCtlValue(cHH);
- /* shift to the right location in the document */
- if (docV || docH)
- {
- SetOrigin(docH, docV);
- OffsetRgn(wPtr->clipRgn, docH, docV);
- }
- /* we'll be ultra-efficient and draw only what
- touches the updateRgn */
- while (mH)
- {
- if (RectInRgn(&((**mH).meterRect), wPtr->clipRgn))
- {
- /* fool ShowMeter() into redrawing the meter */
- (**mH).meterVis = FALSE;
- ShowMeter(mH);
- }
- mH = (**mH).nextMeter;
- }
- if (docV || docH)
- SetOrigin(0, 0);
- clpRect.top = wPtr->portRect.top;
- clpRect.left = wPtr->portRect.left;
- clpRect.bottom = wPtr->portRect.bottom - SCROLLSIZE;
- clpRect.right = wPtr->portRect.right - SCROLLSIZE;
- ClipRect(&clpRect);
- } /* end UpdateContents() */
-
- /* Show two integer values in a little display box at bottom right
- of the window. If you call this function with mode = forDebug, specify
- the WindowPtr and put the two values in newValue and otherValue. */
- void DrawDisplayBox(wPtr, theHandle, mode, newValue, otherValue)
- WindowPtr wPtr;
- void **theHandle;
- DisplayMode mode;
- int newValue, otherValue;
- {
- int i, j;
- int oldFont, oldSize;
- Style oldStyle;
- long leftNum, rightNum;
- char s[20], sr[10], *sPtr;
- Rect displayRect, clpRect;
- MeterHandle mH;
- ControlHandle theCtl, cHH, cHV;
- GrafPtr savePort;
-
- if (DISPLAYBOXWIDTH <= 0) return;
- GetPort(&savePort);
- SetPort(wPtr);
- oldFont = wPtr->txFont;
- oldSize = wPtr->txSize;
- oldStyle = wPtr->txFace; /* sic */
- TextFont(0);
- TextSize(12);
- TextFace(' ');
- displayRect.top = wPtr->portRect.bottom - SCROLLSIZE + 1;
- displayRect.left = wPtr->portRect.right - DISPLAYBOXWIDTH -14;
- displayRect.bottom = wPtr->portRect.bottom + 1;
- displayRect.right = displayRect.left + DISPLAYBOXWIDTH - 1;
- ClipRect(&displayRect);
- EraseRect(&displayRect);
-
- if (mode == forWindow)
- {
- GetScrollHandles(wPtr, &cHH, &cHV);
- leftNum = (long)GetCtlValue(cHH);
- rightNum = (long)GetCtlValue(cHV);
- /* or
- leftNum = wPtr->portRect.right - wPtr->portRect.left - 15;
- rightNum = wPtr->portRect.bottom - wPtr->portRect.top - 15;
- */
- }
- else if (mode == forMeter)
- {
- mH = (MeterHandle)theHandle;
- leftNum = (long)((**mH).meterRect.right - (**mH).meterRect.left);
- rightNum = (long)((**mH).meterRect.bottom - (**mH).meterRect.top);
- }
- else if (mode == forThumb)
- {
- GetScrollHandles(wPtr, &cHH, &cHV);
- theCtl = (ControlHandle)theHandle;
- if (theCtl == cHH)
- {
- leftNum = (long)newValue;
- rightNum = (long)GetCtlValue(cHV);
- }
- else
- {
- leftNum = (long)GetCtlValue(cHH);
- rightNum = (long)newValue;
- }
- }
- else if (mode == forDebug)
- {
- leftNum = (long)newValue;
- rightNum = (long)otherValue;
- }
- else
- {
- leftNum = 0L;
- rightNum = 0L;
- }
- NumToString(leftNum, s);
- NumToString(rightNum, sr);
- /* Concatenate sr into s with space between. */
- j = s[0];
- s[++j] = ' ';
- for (i = 1, sPtr = &(s[j + 1]); i <= sr[0]; ++i)
- *sPtr++ = sr[i];
- s[0] += i; /* note 1 extra for space */
- TextBox(&(s[1]), (Byte)(s[0]), &displayRect, teJustCenter);
-
- clpRect.top = thePort->portRect.top;
- clpRect.left = thePort->portRect.left;
- clpRect.bottom = thePort->portRect.bottom - SCROLLSIZE;
- clpRect.right = thePort->portRect.right - SCROLLSIZE;
- ClipRect(&clpRect);
- TextFont(oldFont);
- TextSize(oldSize);
- TextFace(oldStyle);
- SetPort(savePort);
- } /* end DrawDisplayBox() */
-
- /* Both DoZoomWindow() and DoGrowWindow() handle the potentially
- embarrassing problem of moving around in a document of fixed size
- without scrolling out into the Twilight Zone. */
- void DoZoomWindow (wPtr, part)
- WindowPtr wPtr;
- int part;
- {
- int oldV, oldH, newV, newH;
- int vertRange, horRange;
- int curValH, curMaxH, curValV, curMaxV;
- Point dS;
- ControlHandle cHH, cHV;
-
- /* get control handles */
- GetScrollHandles(wPtr, &cHH, &cHV);
- oldV = (wPtr->portRect).bottom - (wPtr->portRect).top;
- oldH = (wPtr->portRect).right - (wPtr->portRect).left;
- curValH = GetCtlValue(cHH);
- curMaxH = GetCtlMax(cHH);
- curValV = GetCtlValue(cHV);
- curMaxV = GetCtlMax(cHV);
- ZoomWindow(wPtr, part, TRUE);
- InvalRect(&(wPtr->portRect));
- newV = (wPtr->portRect).bottom - (wPtr->portRect).top;
- newH = (wPtr->portRect).right - (wPtr->portRect).left;
- SetRect(&((**cHV).contrlRect), wPtr->portRect.right - SCROLLSIZE,
- wPtr->portRect.top - 1, wPtr->portRect.right + 1,
- wPtr->portRect.bottom - 14);
- SetRect(&((**cHH).contrlRect), wPtr->portRect.left - 1,
- wPtr->portRect.bottom - SCROLLSIZE, wPtr->portRect.right - DISPLAYBOXWIDTH - 14,
- wPtr->portRect.bottom + 1);
- vertRange = MAXWINDOWHEIGHT - (wPtr->portRect.bottom - wPtr->portRect.top);
- vertRange = (vertRange > 0) ? vertRange : 0;
- horRange = MAXWINDOWWIDTH - (wPtr->portRect.right - wPtr->portRect.left);
- horRange = (horRange > 0) ? horRange : 0;
- SetCtlMax(cHV, vertRange);
- SetCtlMax(cHH, horRange);
- if (vertRange == 0)
- HiliteControl(cHV, 255);
- else
- HiliteControl(cHV, 0);
- if (horRange == 0)
- HiliteControl(cHH, 255);
- else
- HiliteControl(cHH, 0);
- /* "Scroll" if running off the bottom or right. The whole window has
- been invalidated above, so we just shift the scroll bars and
- then let the update event take care of the redrawing later. */
- /* dS.h(or .v) = overshoot = amount potentially exposed by zoom less
- amount available to be exposed; potential amount = increase in
- window size; amount available = maximum amount left unseen, which is
- the (prezoom) control Max, less amount that has already scrolled by,
- which is the (prezoom) control Value. If you grok that, you've got
- scroll bars in the bag! */
- dS.h = newH - oldH - curMaxH + curValH;
- dS.h = (dS.h > 0) ? dS.h : 0;
- dS.v = newV - oldV - curMaxV + curValV;
- dS.v = (dS.v > 0) ? dS.v : 0;
- if (dS.h > 0 || dS.v > 0)
- {
- SetCtlValue(cHV, GetCtlValue(cHV) - dS.v);
- SetCtlValue(cHH, GetCtlValue(cHH) - dS.h);
- }
- } /* end DoZoomWindow() */
-
- void DoGrowWindow(event)
- EventRecord *event;
- {
- int winWidth, winHeight;
- int horRange, vertRange;
- int oldV, oldH, newV, newH;
- int curValH, curMaxH, curValV, curMaxV;
- long growResult;
- Point dS;
- Rect limitRect, badRect;
- ControlHandle cHH, cHV;
- RgnHandle tempRgn;
- WindowPtr wPtr = FrontWindow();
-
- winHeight = ((screenBits.bounds.bottom - screenBits.bounds.top - 22) <= MAXWINDOWHEIGHT) ?
- (screenBits.bounds.bottom - screenBits.bounds.top - 22) : MAXWINDOWHEIGHT;
- winWidth = ((screenBits.bounds.right - screenBits.bounds.left - 2) <= MAXWINDOWWIDTH) ?
- (screenBits.bounds.right - screenBits.bounds.left - 2) : MAXWINDOWWIDTH;
- limitRect.top = 130;
- limitRect.left = 250;
- limitRect.bottom = winHeight + 1;
- limitRect.right = winWidth + 1;
- /* get control handles */
- GetScrollHandles(wPtr, &cHH, &cHV);
- oldV = (wPtr->portRect).bottom - (wPtr->portRect).top;
- oldH = (wPtr->portRect).right - (wPtr->portRect).left;
- curValH = GetCtlValue(cHH);
- curMaxH = GetCtlMax(cHH);
- curValV = GetCtlValue(cHV);
- curMaxV = GetCtlMax(cHV);
- growResult = GrowWindow(wPtr, event->where, &limitRect);
- newV = HiWord(growResult);
- newH = LoWord(growResult);
- SizeWindow(wPtr, newH, newV, TRUE);
- ClipRect(&(wPtr->portRect));
- SetRect(&((**cHV).contrlRect), wPtr->portRect.right - SCROLLSIZE,
- wPtr->portRect.top - 1, wPtr->portRect.right + 1,
- wPtr->portRect.bottom - 14);
- SetRect(&((**cHH).contrlRect), wPtr->portRect.left - 1,
- wPtr->portRect.bottom - SCROLLSIZE, wPtr->portRect.right - DISPLAYBOXWIDTH - 14,
- wPtr->portRect.bottom + 1);
- vertRange = MAXWINDOWHEIGHT - (wPtr->portRect.bottom - wPtr->portRect.top);
- vertRange = (vertRange > 0) ? vertRange : 0;
- horRange = MAXWINDOWWIDTH - (wPtr->portRect.right - wPtr->portRect.left);
- horRange = (horRange > 0) ? horRange : 0;
- SetCtlMax(cHV, vertRange);
- SetCtlMax(cHH, horRange);
- if (vertRange == 0)
- HiliteControl(cHV, 255);
- else
- HiliteControl(cHV, 0);
- if (horRange == 0)
- HiliteControl(cHH, 255);
- else
- HiliteControl(cHH, 0);
- /* update scroll bars properly */
- if (newV > oldV)
- {
- badRect.top = oldV - SCROLLSIZE;
- badRect.left = 0;
- badRect.bottom = oldV;
- badRect.right = oldH;
- InvalRect(&badRect);
- }
- else
- {
- badRect.top = (wPtr->portRect).bottom - SCROLLSIZE;
- badRect.left = (wPtr->portRect).left;
- badRect.bottom = (wPtr->portRect).bottom;
- badRect.right = (wPtr->portRect).right;
- InvalRect(&badRect);
- }
- if (newH > oldH)
- {
- badRect.top = 0;
- badRect.left = oldH - SCROLLSIZE;
- badRect.bottom = oldV;
- badRect.right = oldH;
- InvalRect(&badRect);
- }
- else
- {
- badRect.top = (wPtr->portRect).top;
- badRect.left = (wPtr->portRect).right - SCROLLSIZE;
- badRect.bottom = (wPtr->portRect).bottom;
- badRect.right = (wPtr->portRect).right;
- InvalRect(&badRect);
- }
- badRect.top = (wPtr->portRect).top;
- badRect.left = (wPtr->portRect).left;
- badRect.bottom = (wPtr->portRect).bottom - SCROLLSIZE;
- badRect.right = (wPtr->portRect).right - SCROLLSIZE;
- /* Scroll if running off the bottom or right of document.
- The newly exposed part is invalidated. The resulting
- update event will set updateRgn equal to the total invalidated
- region, and UpdateContents() will redraw only that part
- of the window. */
- dS.h = newH - oldH - curMaxH + curValH;
- dS.h = (dS.h > 0) ? dS.h : 0;
- dS.v = newV - oldV - curMaxV + curValV;
- dS.v = (dS.v > 0) ? dS.v : 0;
- if (dS.h > 0 || dS.v > 0)
- {
- ClipRect(&badRect);
- tempRgn = NewRgn();
- SetCtlValue(cHV, GetCtlValue(cHV) - dS.v);
- SetCtlValue(cHH, GetCtlValue(cHH) - dS.h);
- ScrollRect(&badRect, dS.h, dS.v, tempRgn);
- InvalRgn(tempRgn);
- DisposeRgn(tempRgn);
- }
- else
- ClipRect(&badRect);
- } /* end DoGrowWindow() */
-
- void DoCloseWindow()
- {
- WindowPtr wPtr = FrontWindow();
-
- KillMeters(wPtr);
- CloseWindow(wPtr); /* does KillControls() for you */
- } /* end DoCloseWindow() */
-
- Boolean AMeterWindow(wPtr)
- WindowPtr wPtr;
- {
- if (wPtr == (WindowPtr)(&wRecord1) || wPtr == (WindowPtr)(&wRecord2))
- return(TRUE);
- return(FALSE);
- } /* end AMeterWindow() */
-
- void GetScrollHandles(wPtr, cH, cV)
- WindowPtr wPtr;
- ControlHandle *cV, *cH;
- {
- ControlHandle cHH, cHV;
-
- cHH = ((WindowPeek)wPtr)->controlList;
- while (cHH)
- {
- if (GetCRefCon(cHH) == HSCROLL) break;
- cHH = (**cHH).nextControl;
- }
- cHV = ((WindowPeek)wPtr)->controlList;
- while (cHV)
- {
- if (GetCRefCon(cHV) == VSCROLL) break;
- cHV = (**cHV).nextControl;
- }
- *cH = cHH;
- *cV = cHV;
- } /* end AMeterWindow() */
-
- void LocalToDoc(thePt)
- Point *thePt;
- {
- ControlHandle cHH, cHV;
-
- /* get control handles */
- GetScrollHandles(thePort, &cHH, &cHV);
- /* Document coordinates are always at least as large
- as local coord's - a mental picture of the window
- sliding over the document helps.*/
- thePt->v += GetCtlValue(cHV);
- thePt->h += GetCtlValue(cHH);
- } /* end LocalToDoc() */
-
- void MeterProc(mH, theCode)
- MeterHandle mH;
- int theCode;
- {
- long posIncrement = ((**mH).meterMax - (**mH).meterMin)/250L;
- long scrollAmt;
-
- Delay(2L, &scrollAmt);
- switch (theCode)
- {
- case inUpButton:
- scrollAmt = posIncrement/10L;
- if (!scrollAmt)
- scrollAmt = 1L;
- break;
- case inDownButton:
- scrollAmt = -posIncrement/10L;
- if (!scrollAmt)
- scrollAmt = -1L;
- break;
- case inPageUp:
- scrollAmt = posIncrement;
- break;
- case inPageDown:
- scrollAmt = -posIncrement;
- break;
- }
- SetMtrValue(mH, GetMtrValue(mH) + scrollAmt);
- } /* end MeterProc() */
-
- pascal void ScrollProc(theCtl, partCode)
- ControlHandle theCtl;
- int partCode;
- {
- int delta, pageSize, arrowSize, oldValue;
- Point dS;
- Rect viewBnds;
- Boolean horizontal = FALSE;
-
- /* which control, how far */
- if (GetCRefCon(theCtl) == HSCROLL)
- {
- horizontal = TRUE;
- pageSize = (thePort->portRect).right - (thePort->portRect).left - SCROLLSIZE;
- }
- else /* VSCROLL */
- pageSize = (thePort->portRect).bottom - (thePort->portRect).top - SCROLLSIZE;
- arrowSize = pageSize/20;
- /* delta is used to adjust local coord's, which DECREASE if
- up button pressed (we move closer to top of document).
- However, we want the stuff in the window to slide DOWN
- so the sign of dS is reversed from that of delta in
- order that ScrollRect() will work correctly. Hence for
- up button of vertical scroll, delta is negative and
- dS.v is positive (they agree in magnitude unless
- we're at one end or the other of the document).*/
- switch (partCode)
- {
- case inUpButton:
- delta = -arrowSize;
- break;
- case inDownButton:
- delta = arrowSize;
- break;
- case inPageUp:
- delta = -pageSize;
- break;
- case inPageDown:
- delta = pageSize;
- break;
- default:
- delta = 0;
- break;
- } /* end switch */
- ClipRect(&(thePort->portRect));
- oldValue = GetCtlValue(theCtl);
- SetCtlValue(theCtl, oldValue + delta);
- if (horizontal)
- {
- dS.h = oldValue - GetCtlValue(theCtl);
- dS.v = 0;
- }
- else /* vertical */
- {
- dS.v = oldValue - GetCtlValue(theCtl);
- dS.h = 0;
- }
- viewBnds.top = (thePort->portRect).top;
- viewBnds.left = (thePort->portRect).left;
- viewBnds.bottom = (thePort->portRect).bottom - SCROLLSIZE;
- viewBnds.right = (thePort->portRect).right - SCROLLSIZE;
- ScrollRect(&viewBnds, dS.h, dS.v, updateRgn);
- DrawDisplayBox(thePort, 0L, forWindow, 0,0);
- UpdateContents(thePort, TRUE);
- } /* end ScrollProc() */
-
- /* This function will track the mouse and correctly update the value of a scroll bar as the
- thumb is dragged around, in case you might want to update a graphic or number continuously
- as the user moves the thumb about, something TrackControl() doesn't readily allow. Use
- "ThumbControl(startPoint, theCtl);" in place of "if (TrackControl(theCtl,startPoint, 0L))"
- when FindControl() reports an appropriate thumb event, and modify the action calls in this
- routine where indicated. Depending on your needs, you may want to clip differently. For
- generality, this routine decides which scroll bar is which by the same method that the
- Control Manager uses - which way is longer? Much of "while (StillDown())" below is a
- duplication of DragGrayRgn() that lets us tell where we are at all times.
- */
- void ThumbControl(theCtl, startPoint)
- ControlHandle theCtl;
- Point startPoint;
- {
- int newValue, startValue, thickness;
- int mouseRange, controlMin, controlMax;
- long thumbRange, controlRange;
- Point theMouse, thumbStart, thumbMin, thumbMax, newThumbCent, thumbCent, halfThumb;
- Rect controlRect,slopRect, startRect, thumbRect;
- RgnHandle oldClipRgn;
- PenState pState;
- Boolean isHorizontalBar, tracking;
-
- GetPenState(&pState);
- PenMode(patXor);
- PenPat(dkGray);
- PenSize(1,1);
- controlRect = (**theCtl).contrlRect;
- slopRect = controlRect;
- controlMin = GetCtlMin(theCtl);
- controlMax = GetCtlMax(theCtl);
- controlRange = (long)(controlMax - controlMin);
- startValue = GetCtlValue(theCtl);
- newValue = startValue;
- isHorizontalBar = (controlRect.right - controlRect.left) >
- (controlRect.bottom - controlRect.top) ? TRUE : FALSE;
- if (isHorizontalBar)
- {
- thumbStart.v = controlRect.top + (controlRect.bottom - controlRect.top + 1)/2;
- thumbMin.v = thumbMax.v = thumbStart.v;
- thickness = controlRect.bottom - controlRect.top;
- halfThumb.h = thickness/2;
- halfThumb.v = halfThumb.h - 1;
- thumbMin.h = controlRect.left + thickness + (thickness + 1)/2;
- thumbMax.h = controlRect.right - thickness - (thickness + 1)/2;
- thumbRange = (long)(controlRect.right - controlRect.left - 3*thickness);
- thumbStart.h = thumbMin.h + (thumbRange*(startValue - controlMin) + controlRange/2)/controlRange;
- InsetRect(&slopRect, -72, -36);
- }
- else
- {
- thumbStart.h = controlRect.left + (controlRect.right - controlRect.left + 1)/2;
- thumbMin.h = thumbMax.h = thumbStart.h;
- thickness = controlRect.right - controlRect.left;
- halfThumb.v = thickness/2;
- halfThumb.h = halfThumb.v - 1;
- thumbMin.v = controlRect.top + thickness + (thickness + 1)/2;
- thumbMax.v = controlRect.bottom - thickness - (thickness + 1)/2;
- thumbRange = (long)(controlRect.bottom - controlRect.top - 3*thickness);
- thumbStart.v = thumbMin.v + (thumbRange*(startValue - controlMin) + controlRange/2)/controlRange;
- InsetRect(&slopRect, -36, -72);
- }
- if (thumbRange <= 0) return; /* that's a pretty short scroll bar */
- newThumbCent = thumbCent = thumbStart;
- oldClipRgn = NewRgn();
- GetClip(oldClipRgn);
- ClipRect(&controlRect);
- SetRect(&thumbRect, thumbCent.h - halfThumb.h, thumbCent.v - halfThumb.v,
- thumbCent.h + halfThumb.h, thumbCent.v + halfThumb.v);
-
-
- tracking = FALSE;
- while (StillDown())
- {
- ClipRect(&controlRect);
- GetMouse(&theMouse);
- if (PtInRect(theMouse, &slopRect))
- { /* mouse is close to scroll bar - track the thumb */
- /* calculate new thumb center */
- if (isHorizontalBar)
- {
- newThumbCent.h = thumbStart.h + (theMouse.h - startPoint.h);
- if (newThumbCent.h < thumbMin.h)
- newThumbCent.h = thumbMin.h;
- else if (newThumbCent.h > thumbMax.h)
- newThumbCent.h = thumbMax.h;
- }
- else
- {
- newThumbCent.v = thumbStart.v + (theMouse.v - startPoint.v);
- if (newThumbCent.v < thumbMin.v)
- newThumbCent.v = thumbMin.v;
- else if (newThumbCent.v > thumbMax.v)
- newThumbCent.v = thumbMax.v;
- }
- if (tracking)
- {
- if (newThumbCent.h != thumbCent.h || newThumbCent.v != thumbCent.v)
- {
- FrameRect(&thumbRect);
- SetRect(&thumbRect, newThumbCent.h - halfThumb.h, newThumbCent.v - halfThumb.v,
- newThumbCent.h + halfThumb.h, newThumbCent.v + halfThumb.v);
- FrameRect(&thumbRect);
- }
- }
- else /* just entering slop rect */
- {
- SetRect(&thumbRect, newThumbCent.h - halfThumb.h, newThumbCent.v - halfThumb.v,
- newThumbCent.h + halfThumb.h, newThumbCent.v + halfThumb.v);
- FrameRect(&thumbRect);
- tracking = TRUE;
- }
-
- } /* if track the thumb */
- else /* not in slop rect */
- {
- if (tracking)
- { /* just leaving slop rect */
- FrameRect(&thumbRect);
- tracking = FALSE;
- newThumbCent = thumbStart;
- }
- } /* else default to start position */
- if (newThumbCent.h != thumbCent.h || newThumbCent.v != thumbCent.v)
- {
- /* Either thumb has been dragged to new position or mouse has left
- slopRect, in which case thumbCent reverts to thumbStart. */
- /* Calculate control value based on newThumbCent. */
- newValue = (controlRange*(newThumbCent.h - thumbMin.h
- + newThumbCent.v - thumbMin.v) + thumbRange/2)/thumbRange + controlMin;
- thumbCent = newThumbCent;
- /*************************************************************************/
- /* Insert your custom call here - the current control value is "newValue";
- reset the clipRgn if you draw outside the scroll bar!*/
-
- /* Sample thumb action; echo control values to display box. */
- DrawDisplayBox(thePort, (void**)theCtl, forThumb, newValue,0);
- /*************************************************************************/
- }
- } /* while still down */
- if (tracking)
- FrameRect(&thumbRect);
- if (newValue != startValue)
- {
- SetCtlValue(theCtl, newValue);
- /* The control value has changed on mouseup to "newValue" - take
- appropriate action - here we redraw the window */
- InvalRect(&(thePort->portRect));
- }
- else
- {
- /* the control value hasn't changed - reset if necessary */;
- }
- SetClip(oldClipRgn);
- DisposeRgn(oldClipRgn);
- SetPenState(&pState);
- } /* end ThumbControl() */
-
- void PutMetersOnClip(wPtr)
- WindowPtr wPtr;
- {
- Rect theClipRect;
- PicHandle clipPicH;
- RgnHandle oldClipRgn;
- MeterHandle mH = (MeterHandle)(((WindowPeek)wPtr)->refCon);
-
- ZeroScrap();
- theClipRect.top = 0;
- theClipRect.left = 0;
- theClipRect.bottom = DOCHEIGHT;
- theClipRect.right = DOCWIDTH;
- oldClipRgn = NewRgn();
- GetClip(oldClipRgn);
- ClipRect(&theClipRect);
-
- /* draw the picture */
- clipPicH = OpenPicture(&theClipRect);
- while (ValidMeter(mH))
- {
- MeterSnapshot(mH);
- mH = (**mH).nextMeter;
- }
- ClosePicture();
- /* put it on the scrap and clean up */
- HLock(clipPicH);
- PutScrap(GetHandleSize(clipPicH), 'PICT', *clipPicH);
- HUnlock(clipPicH);
- KillPicture(clipPicH);
- SetClip(oldClipRgn);
- DisposeRgn(oldClipRgn);
- } /* end PutMetersOnClip() */
-
- /* End MeterMain.c */